home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 58 / pcpp58a.iso / extras / quake 3 source / Q3A_ToolSource.exe / Main / DRAG.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-02  |  16.5 KB  |  714 lines

  1. #include "stdafx.h"
  2. #include "qe3.h"
  3.  
  4. /*
  5.  
  6.   drag either multiple brushes, or select plane points from
  7.   a single brush.
  8.  
  9. */
  10.  
  11. qboolean    drag_ok;
  12. vec3_t    drag_xvec;
  13. vec3_t    drag_yvec;
  14.  
  15. static    int    buttonstate;
  16. int    pressx, pressy;
  17. static    vec3_t pressdelta;
  18. static    vec3_t vPressStart;
  19. static    int    buttonx, buttony;
  20.  
  21.  
  22. //int        num_move_points;
  23. //float    *move_points[1024];
  24.  
  25. int        lastx, lasty;
  26.  
  27. qboolean    drag_first;
  28.  
  29.  
  30. void    AxializeVector (vec3_t v)
  31. {
  32.     vec3_t    a;
  33.     float    o;
  34.     int        i;
  35.  
  36.     if (!v[0] && !v[1])
  37.         return;
  38.     if (!v[1] && !v[2])
  39.         return;
  40.     if (!v[0] && !v[2])
  41.         return;
  42.  
  43.     for (i=0 ; i<3 ; i++)
  44.         a[i] = fabs(v[i]);
  45.     if (a[0] > a[1] && a[0] > a[2])
  46.         i = 0;
  47.     else if (a[1] > a[0] && a[1] > a[2])
  48.         i = 1;
  49.     else
  50.         i = 2;
  51.  
  52.     o = v[i];
  53.     VectorCopy (vec3_origin, v);
  54.     if (o<0)
  55.         v[i] = -1;
  56.     else
  57.         v[i] = 1;
  58.     
  59. }
  60.  
  61.  
  62. /*
  63. ===========
  64. Drag_Setup
  65. ===========
  66. */
  67. void Drag_Setup (int x, int y, int buttons,
  68.            vec3_t xaxis, vec3_t yaxis,
  69.            vec3_t origin, vec3_t dir)
  70. {
  71.     trace_t    t;
  72.     face_t    *f;
  73.  
  74.     drag_first = true;
  75.     
  76.     VectorCopy (vec3_origin, pressdelta);
  77.     pressx = x;
  78.     pressy = y;
  79.  
  80.     VectorCopy (xaxis, drag_xvec);
  81.     AxializeVector (drag_xvec);
  82.     VectorCopy (yaxis, drag_yvec);
  83.     AxializeVector (drag_yvec);
  84.  
  85.  
  86.     extern void SelectCurvePointByRay (vec3_t org, vec3_t dir, int buttons);
  87.     if (g_qeglobals.d_select_mode == sel_curvepoint)
  88.     {
  89.         //if ((buttons == MK_LBUTTON))
  90.         //  g_qeglobals.d_num_move_points = 0;
  91.  
  92.         SelectCurvePointByRay (origin, dir, buttons);    
  93.         
  94.         if (g_qeglobals.d_num_move_points || g_qeglobals.d_select_mode == sel_area)
  95.         {
  96.             drag_ok = true;
  97.         }
  98.     
  99.         Sys_UpdateWindows(W_ALL);
  100.  
  101.         Undo_Start("drag curve point");
  102.         Undo_AddBrushList(&selected_brushes);
  103.  
  104.         return;
  105.     }
  106.     else
  107.     {
  108.         g_qeglobals.d_num_move_points = 0;
  109.     }
  110.  
  111.     if (selected_brushes.next == &selected_brushes)
  112.     {
  113.         //in this case a new brush is created when the dragging
  114.         //takes place in the XYWnd, An useless undo is created
  115.         //when the dragging takes place in the CamWnd
  116.         Undo_Start("create brush");
  117.  
  118.         Sys_Status("No selection to drag\n", 0);
  119.         return;
  120.     }
  121.  
  122.  
  123.     if (g_qeglobals.d_select_mode == sel_vertex)
  124.     {
  125.         SelectVertexByRay (origin, dir);    
  126.         if (g_qeglobals.d_num_move_points)
  127.         {
  128.             drag_ok = true;
  129.             Undo_Start("drag vertex");
  130.             Undo_AddBrushList(&selected_brushes);
  131.             return;
  132.         }
  133.     }
  134.  
  135.     if (g_qeglobals.d_select_mode == sel_edge)
  136.     {
  137.         SelectEdgeByRay (origin, dir);    
  138.         if (g_qeglobals.d_num_move_points)
  139.         {
  140.             drag_ok = true;
  141.             Undo_Start("drag edge");
  142.             Undo_AddBrushList(&selected_brushes);
  143.             return;
  144.         }
  145.     }
  146.  
  147.  
  148.     //
  149.     // check for direct hit first
  150.     //
  151.     t = Test_Ray (origin, dir, true);
  152.     if (t.selected)
  153.     {
  154.         drag_ok = true;
  155.  
  156.         Undo_Start("drag selection");
  157.         Undo_AddBrushList(&selected_brushes);
  158.  
  159.         if (buttons == (MK_LBUTTON|MK_CONTROL) )
  160.         {
  161.             Sys_Printf ("Shear dragging face\n");
  162.             Brush_SelectFaceForDragging (t.brush, t.face, true);
  163.         }
  164.         else if (buttons == (MK_LBUTTON|MK_CONTROL|MK_SHIFT) )
  165.         {
  166.             Sys_Printf ("Sticky dragging brush\n");
  167.             for (f=t.brush->brush_faces ; f ; f=f->next)
  168.                 Brush_SelectFaceForDragging (t.brush, f, false);
  169.         }
  170.         else
  171.             Sys_Printf ("Dragging entire selection\n");
  172.         
  173.         return;
  174.     }
  175.  
  176.     if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge)
  177.         return;
  178.  
  179.     //
  180.     // check for side hit
  181.     //
  182.     // multiple brushes selected?
  183.     if (selected_brushes.next->next != &selected_brushes)
  184.     {
  185.         // yes, special handling
  186.         bool bOK = (g_PrefsDlg.m_bALTEdge) ? (static_cast<bool>(::GetAsyncKeyState(VK_MENU))) : true;
  187.         if (bOK)
  188.         {
  189.             for (brush_t* pBrush = selected_brushes.next ; pBrush != &selected_brushes ; pBrush = pBrush->next)
  190.             {
  191.                 if (buttons & MK_CONTROL)
  192.                     Brush_SideSelect (pBrush, origin, dir, true);
  193.                 else
  194.                     Brush_SideSelect (pBrush, origin, dir, false);
  195.             }
  196.         }
  197.         else
  198.         {
  199.             Sys_Printf ("press ALT to drag multiple edges\n");
  200.             return;
  201.         }
  202.     }
  203.     else
  204.     {
  205.         // single select.. trying to drag fixed entities handle themselves and just move
  206.         if (buttons & MK_CONTROL)
  207.             Brush_SideSelect (selected_brushes.next, origin, dir, true);
  208.         else
  209.             Brush_SideSelect (selected_brushes.next, origin, dir, false);
  210.     }
  211.  
  212.     Sys_Printf ("Side stretch\n");
  213.     drag_ok = true;
  214.  
  215.     Undo_Start("side stretch");
  216.     Undo_AddBrushList(&selected_brushes);
  217. }
  218.  
  219. entity_t *peLink;
  220.  
  221. void UpdateTarget(vec3_t origin, vec3_t dir)
  222. {
  223.     trace_t    t;
  224.     entity_t *pe;
  225.     int i;
  226.     char sz[128];
  227.  
  228.     t = Test_Ray (origin, dir, 0);
  229.  
  230.     if (!t.brush)
  231.         return;
  232.  
  233.     pe = t.brush->owner;
  234.  
  235.     if (pe == NULL)
  236.         return;
  237.  
  238.     // is this the first?
  239.     if (peLink != NULL)
  240.     {
  241.  
  242.         // Get the target id from out current target
  243.         // if there is no id, make one
  244.  
  245.         i = IntForKey(pe, "target");
  246.         if (i <= 0)
  247.         {
  248.             i = GetUniqueTargetId(1);
  249.             sprintf(sz, "%d", i);
  250.  
  251.             SetKeyValue(pe, "target", sz);
  252.         }
  253.  
  254.         // set the target # into our src
  255.  
  256.         sprintf(sz, "%d", i);
  257.         SetKeyValue(peLink, "targetname", sz);
  258.  
  259.         Sys_UpdateWindows(W_ENTITY);
  260.  
  261.     }
  262.  
  263.     // promote the target to the src
  264.  
  265.     peLink = pe;
  266.     
  267. }
  268.  
  269. /*
  270. ===========
  271. Drag_Begin
  272. //++timo test three button mouse and three button emulation here ?
  273. ===========
  274. */
  275. void Drag_Begin (int x, int y, int buttons,
  276.            vec3_t xaxis, vec3_t yaxis,
  277.            vec3_t origin, vec3_t dir)
  278. {
  279.     trace_t    t;
  280.     bool altdown;
  281.  
  282.     drag_ok = false;
  283.     VectorCopy (vec3_origin, pressdelta);
  284.     VectorCopy (vec3_origin, vPressStart);
  285.     drag_first = true;
  286.     peLink = NULL;
  287.  
  288.     altdown = static_cast<bool>(::GetAsyncKeyState(VK_MENU));
  289.  
  290.     // shift-LBUTTON = select entire brush
  291.     if (buttons == (MK_LBUTTON | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint)
  292.     {
  293.         int nFlag = altdown ? SF_CYCLE : 0;
  294.         if (dir[0] == 0 || dir[1] == 0 || dir[2] == 0)  // extremely low chance of this happening from camera
  295.             Select_Ray (origin, dir, nFlag | SF_ENTITIES_FIRST);    // hack for XY
  296.         else
  297.             Select_Ray (origin, dir, nFlag);
  298.         return;
  299.     }
  300.  
  301.     // ctrl-alt-LBUTTON = multiple brush select without selecting whole entities
  302.     if (buttons == (MK_LBUTTON | MK_CONTROL) && altdown && g_qeglobals.d_select_mode != sel_curvepoint)
  303.     {
  304.         if (dir[0] == 0 || dir[1] == 0 || dir[2] == 0)  // extremely low chance of this happening from camera
  305.             Select_Ray (origin, dir, SF_ENTITIES_FIRST);    // hack for XY
  306.         else
  307.             Select_Ray (origin, dir, 0);
  308.         return;
  309.     }
  310.  
  311.     // ctrl-shift-LBUTTON = select single face
  312.     if (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint)
  313.     {
  314.         Select_Deselect (!static_cast<bool>(::GetAsyncKeyState(VK_MENU)));
  315.         Select_Ray (origin, dir, SF_SINGLEFACE);
  316.         return;
  317.     }
  318.  
  319.  
  320.     // LBUTTON + all other modifiers = manipulate selection
  321.     if (buttons & MK_LBUTTON)
  322.     {
  323.         //
  324.         Drag_Setup (x, y, buttons, xaxis, yaxis, origin, dir);
  325.         return;
  326.     }
  327.  
  328.     int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
  329.     // middle button = grab texture
  330.     if (buttons == nMouseButton)
  331.     {
  332.         t = Test_Ray (origin, dir, false);
  333.         if (t.face)
  334.         {
  335.             g_qeglobals.d_new_brush_bottom_z = t.brush->mins[2];
  336.             g_qeglobals.d_new_brush_top_z = t.brush->maxs[2];
  337.             // use a local brushprimit_texdef fitted to a default 2x2 texture
  338.             brushprimit_texdef_t bp_local;
  339.             ConvertTexMatWithQTexture( &t.face->brushprimit_texdef, t.face->d_texture, &bp_local, NULL );
  340.             Texture_SetTexture ( &t.face->texdef, &bp_local, false, GETPLUGINTEXDEF(t.face));
  341.             UpdateSurfaceDialog();
  342.             UpdatePatchInspector();
  343.         }
  344.         else
  345.             Sys_Printf ("Did not select a texture\n");
  346.         return;
  347.     }
  348.  
  349.     // ctrl-middle button = set entire brush to texture
  350.     if (buttons == (nMouseButton|MK_CONTROL) )
  351.     {
  352.         t = Test_Ray (origin, dir, false);
  353.         if (t.brush)
  354.         {
  355.             if (t.brush->brush_faces->texdef.name[0] == '(')
  356.                 Sys_Printf ("Can't change an entity texture\n");
  357.             else
  358.             {
  359.                 Brush_SetTexture (t.brush, &g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef, false, static_cast<IPluginTexdef *>( g_qeglobals.d_texturewin.pTexdef ) );
  360.                 Sys_UpdateWindows (W_ALL);
  361.             }
  362.         }
  363.         else
  364.             Sys_Printf ("Didn't hit a btrush\n");
  365.         return;
  366.     }
  367.  
  368.     // ctrl-shift-middle button = set single face to texture
  369.     if (buttons == (nMouseButton|MK_SHIFT|MK_CONTROL) )
  370.     {
  371.         t = Test_Ray (origin, dir, false);
  372.         if (t.brush)
  373.         {
  374.             if (t.brush->brush_faces->texdef.name[0] == '(')
  375.                 Sys_Printf ("Can't change an entity texture\n");
  376.             else
  377.             {
  378.                 SetFaceTexdef (t.brush, t.face, &g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef);
  379.                 Brush_Build( t.brush );
  380.                 Sys_UpdateWindows (W_ALL);
  381.             }
  382.         }
  383.         else
  384.             Sys_Printf ("Didn't hit a btrush\n");
  385.         return;
  386.     }
  387.  
  388.     if (buttons == (nMouseButton | MK_SHIFT))
  389.     {
  390.         Sys_Printf("Set brush face texture info\n");
  391.         t = Test_Ray (origin, dir, false);
  392.         if (t.brush)
  393.         {
  394.             if (t.brush->brush_faces->texdef.name[0] == '(')
  395.       {
  396.         if (t.brush->owner->eclass->nShowFlags & ECLASS_LIGHT)
  397.         {
  398.           CString strBuff;
  399.           qtexture_t* pTex = Texture_ForName(g_qeglobals.d_texturewin.texdef.name);
  400.           if (pTex)
  401.           {
  402.             vec3_t vColor;
  403.             VectorCopy(pTex->color, vColor);
  404.  
  405.             float fLargest = 0.0f;
  406.             for (int i = 0; i < 3; i++)
  407.             {
  408.                   if (vColor[i] > fLargest)
  409.                       fLargest = vColor[i];
  410.             }
  411.                 
  412.                 if (fLargest == 0.0f)
  413.                 {
  414.               vColor[0] = vColor[1] = vColor[2] = 1.0f;
  415.             }
  416.                 else
  417.                 {
  418.                     float fScale = 1.0f / fLargest;
  419.               for (int i = 0; i < 3; i++)
  420.               {
  421.                 vColor[i] *= fScale;
  422.               }
  423.             }
  424.             strBuff.Format("%f %f %f",pTex->color[0], pTex->color[1], pTex->color[2]);
  425.             SetKeyValue(t.brush->owner, "_color", strBuff.GetBuffer(0));
  426.                     Sys_UpdateWindows (W_ALL);
  427.           }
  428.         }
  429.         else
  430.         {
  431.                   Sys_Printf ("Can't select an entity brush face\n");
  432.         }
  433.       }
  434.             else
  435.             {
  436.           //strcpy(t.face->texdef.name,g_qeglobals.d_texturewin.texdef.name);
  437.           t.face->texdef.SetName(g_qeglobals.d_texturewin.texdef.name);
  438.                 Brush_Build(t.brush);
  439.                 Sys_UpdateWindows (W_ALL);
  440.             }
  441.         }
  442.         else
  443.             Sys_Printf ("Didn't hit a brush\n");
  444.         return;
  445.     }
  446.  
  447. }
  448.  
  449.  
  450. //
  451. //===========
  452. //MoveSelection
  453. //===========
  454. //
  455. void MoveSelection (vec3_t move)
  456. {
  457.     int        i, success;
  458.     brush_t    *b;
  459.     CString strStatus;
  460.     vec3_t vTemp, vTemp2, end;
  461.  
  462.     if (!move[0] && !move[1] && !move[2])
  463.         return;
  464.  
  465.     move[0] = (g_nScaleHow & SCALE_X) ? 0 : move[0];
  466.     move[1] = (g_nScaleHow & SCALE_Y) ? 0 : move[1];
  467.   move[2] = (g_nScaleHow & SCALE_Z) ? 0 : move[2];
  468.  
  469.     if (g_pParentWnd->ActiveXY()->RotateMode() || g_bPatchBendMode)
  470.     {
  471.         float fDeg = -move[2];
  472.         float fAdj = move[2];
  473.         int nAxis = 0;
  474.         if (g_pParentWnd->ActiveXY()->GetViewType() == XY)
  475.         {
  476.             fDeg = -move[1];
  477.             fAdj = move[1];
  478.             nAxis = 2;
  479.         }
  480.         else 
  481.             if (g_pParentWnd->ActiveXY()->GetViewType() == XZ)
  482.         {
  483.             fDeg = move[2];
  484.             fAdj = move[2];
  485.             nAxis = 1;
  486.         }
  487.         else
  488.             nAxis = 0;
  489.  
  490.         g_pParentWnd->ActiveXY()->Rotation()[nAxis] += fAdj;
  491.         strStatus.Format("%s x:: %.1f  y:: %.1f  z:: %.1f", (g_bPatchBendMode) ? "Bend angle" : "Rotation", g_pParentWnd->ActiveXY()->Rotation()[0], g_pParentWnd->ActiveXY()->Rotation()[1], g_pParentWnd->ActiveXY()->Rotation()[2]);
  492.         g_pParentWnd->SetStatusText(2, strStatus);
  493.  
  494.         if (g_bPatchBendMode)
  495.         {
  496.             Patch_SelectBendNormal();
  497.             Select_RotateAxis(nAxis, fDeg*2, false, true);
  498.             Patch_SelectBendAxis();
  499.             Select_RotateAxis(nAxis, fDeg, false, true);
  500.         }
  501.         else
  502.         {
  503.             Select_RotateAxis(nAxis, fDeg, false, true);
  504.         }
  505.         return;
  506.     }
  507.  
  508.     if (g_pParentWnd->ActiveXY()->ScaleMode())
  509.     {
  510.         vec3_t v;
  511.         v[0] = v[1] = v[2] = 1.0;
  512.         if (move[1] > 0)
  513.         {
  514.             v[0] = 1.1;
  515.             v[1] = 1.1;
  516.             v[2] = 1.1;
  517.         }
  518.         else 
  519.             if (move[1] < 0)
  520.         {
  521.             v[0] = 0.9;
  522.             v[1] = 0.9;
  523.             v[2] = 0.9;
  524.         }
  525.  
  526.             Select_Scale((g_nScaleHow & SCALE_X) ? 1.0 : v[0],
  527.                                      (g_nScaleHow & SCALE_Y) ? 1.0 : v[1],
  528.                                    (g_nScaleHow & SCALE_Z) ? 1.0 : v[2]);
  529.         Sys_UpdateWindows (W_ALL);
  530.         return;
  531.     }
  532.  
  533.  
  534.     vec3_t vDistance;
  535.     VectorSubtract(pressdelta, vPressStart, vDistance);
  536.     strStatus.Format("Distance x: %.1f  y: %.1f  z: %.1f", vDistance[0], vDistance[1], vDistance[2]);
  537.     g_pParentWnd->SetStatusText(3, strStatus);
  538.  
  539.     //
  540.     // dragging only a part of the selection
  541.     //
  542.  
  543.     // this is fairly crappy way to deal with curvepoint and area selection
  544.     // but it touches the smallest amount of code this way
  545.     // 
  546.     if (g_qeglobals.d_num_move_points || g_qeglobals.d_select_mode == sel_area)
  547.     {
  548.         //area selection
  549.         if (g_qeglobals.d_select_mode == sel_area)
  550.         {
  551.             VectorAdd(g_qeglobals.d_vAreaBR, move, g_qeglobals.d_vAreaBR);
  552.             return;
  553.         }
  554.         //curve point selection
  555.         if (g_qeglobals.d_select_mode == sel_curvepoint)
  556.         {
  557.             Patch_UpdateSelected(move);
  558.             return;
  559.         }
  560.         //vertex selection
  561.         if (g_qeglobals.d_select_mode == sel_vertex)
  562.         {
  563.             success = true;
  564.             for (b = selected_brushes.next; b != &selected_brushes; b = b->next)
  565.             {
  566.                 success &= Brush_MoveVertex(b, g_qeglobals.d_move_points[0], move, end, true);
  567.             }
  568.             if (success)
  569.                 VectorCopy(end, g_qeglobals.d_move_points[0]);
  570.             return;
  571.         }
  572.         //all other selection types
  573.         for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
  574.             VectorAdd (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);
  575.         //VectorScale(move, .5, move);
  576.         //for (i=0 ; i<g_qeglobals.d_num_move_points2 ; i++)
  577.         //    VectorAdd (g_qeglobals.d_move_points2[i], move, g_qeglobals.d_move_points2[i]);
  578.         for (b = selected_brushes.next; b != &selected_brushes; b = b->next)
  579.         {
  580.             VectorCopy(b->maxs, vTemp);
  581.             VectorSubtract(vTemp, b->mins, vTemp);
  582.             Brush_Build( b );
  583.             for (i=0 ; i<3 ; i++)
  584.                 if (b->mins[i] > b->maxs[i]
  585.                 || b->maxs[i] - b->mins[i] > MAX_BRUSH_SIZE)
  586.                     break;    // dragged backwards or fucked up
  587.             if (i != 3)
  588.                 break;
  589.             if (b->patchBrush)
  590.             {
  591.                 VectorCopy(b->maxs, vTemp2);
  592.                 VectorSubtract(vTemp2, b->mins, vTemp2);
  593.                 VectorSubtract(vTemp2, vTemp, vTemp2);
  594.                 //if (!Patch_DragScale(b->nPatchID, vTemp2, move))
  595.                 if (!Patch_DragScale(b->pPatch, vTemp2, move))
  596.                 {
  597.                     b = NULL;
  598.                     break;
  599.                 }
  600.             }
  601.         }
  602.         // if any of the brushes were crushed out of existance
  603.         // calcel the entire move
  604.         if (b != &selected_brushes)
  605.         {
  606.             Sys_Printf ("Brush dragged backwards, move canceled\n");
  607.             for (i=0 ; i<g_qeglobals.d_num_move_points ; i++)
  608.                 VectorSubtract (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]);
  609.  
  610.             for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
  611.                 Brush_Build( b );
  612.         }
  613.  
  614.     }
  615.     else
  616.     {
  617.         // reset face originals from vertex edit mode
  618.         // this is dirty, but unfortunately necessary because Brush_Build
  619.         // can remove windings
  620.         for (b = selected_brushes.next; b != &selected_brushes; b = b->next)
  621.         {
  622.             Brush_ResetFaceOriginals(b);
  623.         }
  624.         //
  625.         // if there are lots of brushes selected, just translate instead
  626.         // of rebuilding the brushes
  627.         //
  628.         if (drag_yvec[2] == 0 && selected_brushes.next->next != &selected_brushes)
  629.         {
  630.             Select_Move (move);
  631.             //VectorAdd (g_qeglobals.d_select_translate, move, g_qeglobals.d_select_translate);
  632.         }
  633.         else
  634.         {
  635.             Select_Move (move);
  636.         }
  637.     }
  638. }
  639.  
  640. /*
  641. ===========
  642. Drag_MouseMoved
  643. ===========
  644. */
  645. void Drag_MouseMoved (int x, int y, int buttons)
  646. {
  647.     vec3_t    move, delta;
  648.     int        i;
  649.  
  650.     if (!buttons)
  651.     {
  652.         drag_ok = false;
  653.         return;
  654.     }
  655.     if (!drag_ok)
  656.         return;
  657.  
  658.     // clear along one axis
  659.     if (buttons & MK_SHIFT)
  660.     {
  661.         drag_first = false;
  662.         if (abs(x-pressx) > abs(y-pressy))
  663.             y = pressy;
  664.         else
  665.             x = pressx;
  666.     }
  667.  
  668.  
  669.     for (i=0 ; i<3 ; i++)
  670.     {
  671.         move[i] = drag_xvec[i]*(x - pressx)    + drag_yvec[i]*(y - pressy);
  672.     if (!g_PrefsDlg.m_bNoClamp)
  673.     {
  674.           move[i] = floor(move[i]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize;
  675.     }
  676.     }
  677.  
  678.     VectorSubtract (move, pressdelta, delta);
  679.     VectorCopy (move, pressdelta);
  680.  
  681.   MoveSelection (delta);
  682.  
  683. }
  684.  
  685. /*
  686. ===========
  687. Drag_MouseUp
  688. ===========
  689. */
  690. void Drag_MouseUp (int nButtons)
  691. {
  692.     Sys_Status ("drag completed.", 0);
  693.  
  694.   if (g_qeglobals.d_select_mode == sel_area)
  695.   {
  696.     Patch_SelectAreaPoints();
  697.     g_qeglobals.d_select_mode = sel_curvepoint;
  698.         Sys_UpdateWindows (W_ALL);
  699.   }
  700.     
  701.   if (g_qeglobals.d_select_translate[0] || g_qeglobals.d_select_translate[1] || g_qeglobals.d_select_translate[2])
  702.     {
  703.         Select_Move (g_qeglobals.d_select_translate);
  704.         VectorCopy (vec3_origin, g_qeglobals.d_select_translate);
  705.         Sys_UpdateWindows (W_CAMERA);
  706.     }
  707.   
  708.   g_pParentWnd->SetStatusText(3, "");
  709.  
  710.     //
  711.     Undo_EndBrushList(&selected_brushes);
  712.     Undo_End();
  713. }
  714.